package com.gillion.grape.fros.ui.util;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import org.xml.sax.SAXException;

import com.gillion.grape.core.Logger;
import com.gillion.grape.core.utils.ProjectConfig;
import com.gillion.grape.core.utils.Utils;

public class XmlUtil {

	private String filePath;

	private Document document;

	public XmlUtil(String filePath) {
		this.filePath = filePath;
	}

	private Element getRootElement() throws DocumentException {
		File file = new File(this.filePath);
		SAXReader reader = new SAXReader();
		try {
			reader.setFeature("", false);
		} catch (SAXException e) {
		}
		try {
			document = reader.read(file);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return document.getRootElement();
	}

	private void writeXml() {
		File file = new File(this.filePath);
		XMLWriter writer = null;
		try {
			if (file.exists()) {
				file.delete();
			}
			OutputFormat format = OutputFormat.createPrettyPrint(); 
			writer = new XMLWriter(new FileOutputStream(file),format);
			writer.write(document);
			writer.close();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (writer != null) {
				try {
					writer.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	private Element getElementByQualifiedName(Element element, String qualifiedName) {
		for (Iterator<Element> i_1 = element.elementIterator(); i_1.hasNext();) {
			Element foo_1 = (Element) i_1.next();
			if (!qualifiedName.equals(foo_1.getQualifiedName()) && foo_1.elements().size() < 1) {
				continue;
			} else if (!qualifiedName.equals(foo_1.getQualifiedName()) && foo_1.elements().size() > 1) {
				getElementByQualifiedName(foo_1, qualifiedName);
			} else {
				return foo_1;
			}
		}
		return null;
	}

	public Element getElementByQualifiedName(String qualifiedName) {
		try {
			return this.getElementByQualifiedName(getRootElement(), qualifiedName);
		} catch (DocumentException e) {
			e.printStackTrace();
		}
		return null;
	}

	public List<Element> getChildElemnetsByQualifiedName(String qualifiedName) {
		try {
			Element root = getRootElement();
			Element element = getElementByQualifiedName(root, qualifiedName);
			return element.elements();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	public List<Element> getChildElemnetsByRoot() {
		try {
			return getRootElement().elements();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	public void appendElement(String parentElementQualifiedName, String childElementQualifiedName, Map<String, String> attributeNameValue) {
		Element element = getElementByQualifiedName(parentElementQualifiedName).addElement(childElementQualifiedName);
		for (Iterator<String> keys = attributeNameValue.keySet().iterator(); keys.hasNext();) {
			String attributeName = (String) keys.next();
			element.addAttribute(attributeName, attributeNameValue.get(attributeName));
		}
		this.writeXml();
	}

	public void appendElementToRoot(String childElementQualifiedName, Map<String, String> attributeNameValue) {
		try {
			Element element = getRootElement().addElement(childElementQualifiedName);
			for (Iterator<String> keys = attributeNameValue.keySet().iterator(); keys.hasNext();) {
				String attributeName = (String) keys.next();
				element.addAttribute(attributeName, attributeNameValue.get(attributeName));
			}
			this.writeXml();
		} catch (DocumentException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 在application-initbean.xml中加入模块的国际化信息
	 * 
	 * @param moduleCode 模块名
	 * @author chich
	 * @since 20120205
	 */
	public static void addI18nConfigToApplicationInitBean(String moduleCode ,String newProject){
		String projectPath = Utils.getCurrentProjectPath();
		//begin add by taiyuan 20120718  如果有值，则更改路径/G:/runtime-EclipseApplication/wef_template_server000
		if(newProject!=null&&newProject.trim().length()>0){
			String arry [] = projectPath.split("\\/"); 
			projectPath = projectPath.substring(1,projectPath.length()-arry[arry.length-1].toString().length())+newProject; 
		}
     //end add by taiyuan 20120718
		String filePath = new StringBuilder(projectPath)
							.append(File.separator)
							.append("src/resource/spring")
							.append(File.separator)
							.append("application-initbean.xml")
							.toString();
		org.dom4j.Document document = Dom4jUtil.loadXml2Document(filePath);
		if(document != null){
			String moduleI18nConfig = new StringBuilder("i18n.")
										.append(moduleCode)
										.toString();
			org.dom4j.Element root = document.getRootElement();
			org.dom4j.Element resourceManagerBean = Dom4jUtil.getChildElementByAttribute(root, "id", "resourceManager");
			org.dom4j.Element eleConfig = Dom4jUtil.getChildElementByAttribute(resourceManagerBean, "name", "configs");
			org.dom4j.Element eleConfigValue = Dom4jUtil.getChildElementByTagName(eleConfig, "value");
			String oldI18nConfig = eleConfigValue.getText();
			if((oldI18nConfig+",").indexOf(moduleI18nConfig+",") == -1){
				oldI18nConfig = oldI18nConfig + "," + moduleI18nConfig;
				eleConfigValue.setText(oldI18nConfig);
				Dom4jUtil.saveDocument2File(document, filePath);
				Logger.logInfo("application-initbean.xml已更新完成");
			}
		}
	}
	
	/**
	 * 在application-hibernate.xml中加入模块的映射信息
	 * 
	 * @param moduleCode 模块名
	 * @author chich
	 * @since 20120205
	 */
	public static void addHbmConfigToApplicationHibernate(String moduleCode,ProjectConfig projectConfig,String newProject){
		boolean flag = false;
		String projectPath = Utils.getCurrentProjectPath();
		//begin add by taiyuan 20120718  如果有值，则更改路径/G:/runtime-EclipseApplication/wef_template_server000
				if(newProject!=null&&newProject.trim().length()>0){
					String arry [] = projectPath.split("\\/"); 
					projectPath = projectPath.substring(1,projectPath.length()-arry[arry.length-1].toString().length())+newProject; 
				}
		//end add by taiyuan 20120718
				
		String filePath = new StringBuilder(projectPath)
							.append(File.separator)
							.append("src/resource/spring")
							.append(File.separator)
							.append("application-hibernate.xml")
							.toString();
		org.dom4j.Document document = Dom4jUtil.loadXml2Document(filePath);
		if(document != null&&(newProject==null||newProject.trim().length()==0)){
			String nameSpace = projectConfig.getNameSpace().replace(".", "/");
			
			String moduleHbmConfig = new StringBuilder("classpath:")
										.append(nameSpace)
										.append("/")
										.append(moduleCode).append("/hbm/*.hbm.xml")
										.toString();
			org.dom4j.Element root = document.getRootElement();
			org.dom4j.Element sessionFactoryBean = Dom4jUtil.getChildElementByAttribute(root, "id", "sessionFactory");
			
			// sessionFactoryBean的子节点mappingLocations
			org.dom4j.Element mappingLocationsConfig = Dom4jUtil.getChildElementByAttribute(sessionFactoryBean, "name", "mappingLocations");
			
			// list列表
			Iterator listIterator = mappingLocationsConfig.elementIterator("list");
			while (listIterator.hasNext()) {
				// list节点
				org.dom4j.Element listNode = (org.dom4j.Element) listIterator.next();
				// value列表
				Iterator valueIterator = listNode.elementIterator("value");
				while (valueIterator.hasNext()) {
					// value节点
					org.dom4j.Element valueNode = (org.dom4j.Element) valueIterator.next();
					if (valueNode.getText().equals(moduleHbmConfig)){
						flag = true;
						break;
					}
				}
				if(!flag){
					Element newElement =listNode.addElement("value");
					newElement.setText(moduleHbmConfig);
					Dom4jUtil.saveDocument2File(document, filePath);
					Logger.logInfo("application-hibernate.xml已更新完成");
				}
			}
		}
		
		if(document != null&&newProject != null&&newProject.trim().length()>0){
			String nameSpace = projectConfig.getNameSpace().replace(".", "/");
			String moduleHbmConfig = new StringBuilder("\\WEB-INF\\lib\\")
										.append(Utils.getCurrentProject().getName()).append(".jar")
										.toString();
			org.dom4j.Element root = document.getRootElement();
			org.dom4j.Element sessionFactoryBean = Dom4jUtil.getChildElementByAttribute(root, "id", "sessionFactory");
			
			// sessionFactoryBean的子节点mappingLocations
			org.dom4j.Element mappingLocationsConfig = Dom4jUtil.getChildElementByAttribute(sessionFactoryBean, "name", "mappingJarLocations");
			
			// list列表
			Iterator listIterator = mappingLocationsConfig.elementIterator("list");
			while (listIterator.hasNext()) {
				// list节点
				org.dom4j.Element listNode = (org.dom4j.Element) listIterator.next();
				// value列表
				Iterator valueIterator = listNode.elementIterator("value");
				while (valueIterator.hasNext()) {
					// value节点
					org.dom4j.Element valueNode = (org.dom4j.Element) valueIterator.next();
					if (valueNode.getText().equals(moduleHbmConfig)){
						flag = true;
						break;
					}
				}
				if(!flag){
					Element newElement =listNode.addElement("value");
					newElement.setText(moduleHbmConfig);
					Dom4jUtil.saveDocument2File(document, filePath);
					Logger.logInfo("application-hibernate.xml JAR已更新完成");
				}
			}
		}
		
	}
	
	/**
	 * 在web.xml中加入模块的dwr信息
	 * 
	 * @param moduleCode 模块名
	 * @author chich
	 * @since 20120206
	 */
	@SuppressWarnings("unchecked")
	public static void addDwrToWebXml(String moduleCode,ProjectConfig projectConfig,String newProject){
		boolean flag = false;
		String projectPath = Utils.getCurrentProjectPath();
		
		//begin add by taiyuan 20120718  如果有值，则更改路径/G:/runtime-EclipseApplication/wef_template_server000
		if(newProject!=null&&newProject.trim().length()>0){
			String arry [] = projectPath.split("\\/"); 
			projectPath = projectPath.substring(1,projectPath.length()-arry[arry.length-1].toString().length())+newProject; 
		}
      //end add by taiyuan 20120718
		
		String filePath = new StringBuilder(projectPath)
							.append(File.separator)
							.append("WebContent/WEB-INF")
							.append(File.separator)
							.append("web.xml")
							.toString();
		org.dom4j.Document document = Dom4jUtil.loadXml2Document(filePath);
		if(document != null){
			// src/resource/dwr/dwr-common.xml
			String moduleDwrConfig = new StringBuilder("/WEB-INF/classes/dwr/")
										.append("dwr-").append(moduleCode).append(".xml")
										.toString();
			org.dom4j.Element root = document.getRootElement();
			
			// dwrConfig
			org.dom4j.Element dwrConfigServlet = Dom4jUtil.getChildElementByAttribute(root, "id", "dwrConfig");
			
			// param列表
			Iterator initParamIterator = dwrConfigServlet.elementIterator("init-param");
			org.dom4j.Element initParamNode = null;
			int count = 0;
			while (initParamIterator.hasNext()) {
				count++;
				// param节点
				initParamNode = (org.dom4j.Element) initParamIterator.next();
				// value列表
				Iterator paramValueIterator = initParamNode.elementIterator("param-value");
				while (paramValueIterator.hasNext()) {
					// value节点
					org.dom4j.Element paramValueNode = (org.dom4j.Element) paramValueIterator.next();
					if (paramValueNode.getText().equals(moduleDwrConfig)){
						flag = true;
						break;
					}
				}
			}
			//针对WEF3.0
			if(!flag && count > 0){
				Element newElement = (Element) initParamNode.clone(); 
				newElement.element("param-name").setText("config-"+moduleCode);
				newElement.element("param-value").setText(moduleDwrConfig);
				//根据给定位置插入新节点 add by chich @20120303 插入位置待商榷.
				dwrConfigServlet.elements().add(dwrConfigServlet.elements().size() > 4 ? dwrConfigServlet.elements().size() - 2 : 2, newElement);
				Dom4jUtil.saveDocument2File(document, filePath);
				Logger.logInfo("web.xml已更新完成");
			}
		}
	}
	
	/**
	 * 格式化xml
	 * 
	 * @param str
	 * @return
	 * @throws UnsupportedEncodingException
	 * @throws IOException
	 * @throws DocumentException
	 * 
	 * @author chich
	 * @since 20120206
	 */
	public static String format(String str)
			throws UnsupportedEncodingException, IOException, DocumentException {
		SAXReader reader = new SAXReader();
		try {
			reader.setFeature("", false);
		} catch (SAXException e) {
		}
		// 创建一个串的字符输入流
		StringReader in = new StringReader(str);
		Document doc = reader.read(in);
		// 创建输出格式
		OutputFormat formater = OutputFormat.createPrettyPrint();
		// 设置xml的输出编码
		formater.setEncoding("UTF-8");
		// 创建输出(目标)
		StringWriter out = new StringWriter();
		// 创建输出流
		XMLWriter writer = new XMLWriter(out, formater);
		// 输出格式化的串到目标中，执行后。格式化后的串保存在out中。
		writer.write(doc);
		// 返回我们格式化后的结果
		return out.toString();
	}
	
	public static Document parseXMLString(String xmlContent,SAXReader reader){
		try {
			return DocumentHelper.parseText(xmlContent);
		} catch (Exception e) {
			Logger.logError(e);
		}
		return null;
	}

	public static void main(String[] args) {
		XmlUtil flexMxmlUtil = new XmlUtil("E:/runtime-com.gillion.grape.application/f_server/flex_src/com/flex/delegate/FlexDelegate.mxml");

		// 1.
		flexMxmlUtil.getChildElemnetsByQualifiedName("fx:Declarations");

		// 2.
		Map<String, String> map = new HashMap<String, String>();
		map.put("destination", "12321");
		map.put("endpoint", "213254231");
		flexMxmlUtil.appendElement("fx:Declarations", "s:RemoteObject", map);
	}
}
